// 显式实例化（Explicit Instantiation）是什么？
// 显式实例化是指程序员明确告诉编译器在哪个地方生成某个模板的具体实例代码，而不是让编译器在每个用到模板的地方自动生成。这可以有效避免模板实例化代码的冗余，提升编译效率，减少目标文件体积。

// C++ 提供了两种相关语法：
// 1.显式实例化定义（Explicit Instantiation Definition）
// 2.显式实例化声明（Explicit Instantiation Declaration）

// ----------------------------------------------------
// 1. 显式实例化定义
// 语法如下：
template void myfunc<int>(int);
// 这告诉编译器：在本翻译单元（.cpp 文件）中生成 myfunc<int> 的实例化代码。

// 2. 显式实例化声明
// 语法如下：
// extern template void myfunc<int>(int);
// 这告诉编译器：不要在本翻译单元中生成 myfunc<int> 的实例化代码，实例化代码会在别的地方生成。

// ----------------------------------------------------
// 例子
// myfunc.h
#ifndef MYFUNC_H
#define MYFUNC_H

#include <iostream>
template <typename T>
void myfunc(T val)
{
    std::cout << "Value: " << val << std::endl;
}

#endif

// a.cpp
#include "myfunc.h"
void foo() { myfunc(42); }

// b.cpp
#include "myfunc.h"
void bar() { myfunc(100); }

// myfunc.cpp
#include "myfunc.h"

// 显式实例化定义：只在这里生成 myfunc<int> 的代码
template void myfunc<int>(int);

// 修改头文件（可选）
// 为了防止 a.cpp 和 b.cpp 自动实例化，可以在头文件加上“显式实例化声明”：
// myfunc.h
extern template void myfunc<int>(int);
// 没有 extern template 声明时的行为
// 假设你在头文件 myfunc.h 里没有写：
extern template void myfunc<int>(int);
// 而只是在 myfunc.cpp 里写了显式实例化定义：
template void myfunc<int>(int);
// 1. 编译阶段
// 当编译器编译 a.cpp、b.cpp 等调用了 myfunc(42) 的源文件时，由于头文件没有 extern template 声明，编译器会在每个调用的翻译单元里自动进行隐式实例化，也就是每个 .o 文件里都生成一份 myfunc<int> 的代码。
// 同时，myfunc.cpp 里会再生成一份显式实例化的 myfunc<int>。

// 2. 链接阶段
// 链接器会发现有多份 myfunc<int> 的实现（来自 a.o、b.o、myfunc.o）。
// 链接器会选择其中一份（通常是第一个遇到的），其余的会被丢弃，或者如果符号不是 weak linkage，可能会报“multiple definition”错误（取决于编译器和链接器的实现）。

// ------------------------------------------------------------
// 编译和链接流程
// myfunc.cpp 生成 myfunc<int> 的实例化代码。
// a.cpp 和 b.cpp 只会引用，不会各自生成实例化代码，避免冗余。
// 链接时只会有一份 myfunc<int> 的实现。

// ------------------------------------------------------------
// 1. 为什么显式实例化要写在 myfunc.cpp 里，而不是调用的地方？
// 主要原因：避免重复实例化和链接冲突
// 1)如果你在每个调用模板的 .cpp 文件里都写显式实例化定义（如 template void myfunc<int>(int);），那么每个目标文件（.o）都会生成一份 myfunc<int> 的代码，最终链接时会发生“多重定义”错误（multiple definition）。
// 2)最佳实践：只在一个 .cpp 文件里写显式实例化定义（比如 myfunc.cpp），这样所有需要 myfunc<int> 的地方都只会引用这一份实现，避免重复和链接冲突。

// -----------------------------------------------------------